package com.mathcat.mobile.android.util;

import java.util.ArrayList;

public class DaemonThread extends Thread {

	private final static int MAX_THREAD_COUNT = 15;

	private static volatile int count = 0;

	public static DaemonThread create(int priority, boolean force) {
		DaemonThread dt = checkAndCreate(force);
		if (dt != null) {
			dt.setPriority(priority);
			dt.taskList = new ArrayList<Task>(1);
			dt.start();
		}
		return dt;
	}
	
	public static DaemonThread create(int priority, boolean force, ArrayList<Task> taskList) {
		DaemonThread dt = checkAndCreate(force);
		if (dt != null) {
			dt.setPriority(priority);
			dt.taskList = taskList;
			dt.start();
		}
		return dt;		
	}

	public static synchronized DaemonThread checkAndCreate(boolean force) {
		if (count < MAX_THREAD_COUNT || force) {
			count++;
			DaemonThread dt = new DaemonThread();
			return dt;
		}
		return null;
	}
	
	private static synchronized void decreaseCount() {
		count--;
	}
		
	private ArrayList<Task> taskList;

	private boolean running = true;

	private volatile Task currentTask = null;
	
	private DaemonThread() {
	}

	public Task getCurrentTask() {
		return this.currentTask;
	}
		
	public void addTask(Task task) {
		synchronized (taskList) {
			taskList.add(task);
			taskList.notify();
		}
	}

	public void addTask(int index, Task task) {
		synchronized (taskList) {
			taskList.add(0, task);
			taskList.notify();
		}
	}
	
	public boolean removeTask(Task task) {
		boolean ret = false;
		
		if (currentTask == task) {
			currentTask.cancel();
			ret = true;
		} else {
			synchronized (taskList) {
				ret = taskList.remove(task);
			}
		}
		return ret;
	}
	
	public ArrayList<Task> clearAllTask() {
		ArrayList<Task> ret = null;
		synchronized (taskList) {
			ret = new ArrayList<Task>(taskList);
			Task currentTask = this.currentTask;
			if (currentTask != null) {
				currentTask.cancel();
				ret.add(0, currentTask);
			}
			taskList.clear();
		}
		return ret;
	}
	
	public void destroy() {
		this.running = false;
		synchronized (taskList) {
			taskList.clear();
			taskList.notifyAll();
		}
	}

	public void run() {

		while (running) {
			
			ArrayList<Task> taskList = this.taskList;
			synchronized (taskList) {
				if (taskList.size() > 0) {
					currentTask = (Task)taskList.get(0);
					taskList.remove(0);
				} else {
					try {
						taskList.wait();
					} catch (InterruptedException ie) {
					}
					continue;
				}
			}
			
			if (currentTask != null) {
				currentTask.execute();
				currentTask = null;
			}
			
			Thread.yield();
		}
		
		decreaseCount();
	}

}
